﻿using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Linq;
using Microsoft.Net.Http.Headers;
using Microsoft.AspNetCore.WebUtilities;

namespace WL.Think.FileUploader
{
    internal static class FileHelper
    {
        /// <summary>
        /// 处理IFormFile数据，转成二进制数据
        /// </summary>
        /// <param name="formFile"></param>
        /// <param name="extensions">允许的文件扩展名</param>
        /// <param name="limit">文件的大小限制，默认10M</param>
        /// <returns></returns>
        internal static async Task<byte[]> ProcessFormFile(IFormFile formFile, FileUploadOption fileUploadOption)
        {
            if (formFile == null)
            {
                throw new ArgumentNullException(nameof(formFile));
            }
            
            var fileName = WebUtility.HtmlEncode(formFile.Name);
            if(formFile.Length == 0)
            {
                throw new Exception($"[{fileName}] The file is empty.");
            }
            if(formFile.Length > fileUploadOption.FileSizeLimit)
            {
                throw new Exception($"[{fileName}] The file exceeds ${fileUploadOption.FileSizeLimit / 1048576:N1} MB.");
            }

            using var ms = new MemoryStream();
            await formFile.CopyToAsync(ms);

            if (ms.Length == 0)
            {
                throw new Exception($"[{fileName}] The file is empty.");
            }

            if (!IsValidFileExtension(formFile.Name, ms, fileUploadOption.SupportFiles))
            {
                throw new Exception($"[{fileName}] The file type isn't permitted or the file's signature doesn't match the file's extension.");
            }

            return ms.ToArray();
        }


        /// <summary>
        /// 处理流式文件上传
        /// </summary>
        /// <param name="section"></param>
        /// <param name="contentDisposition"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        internal static async Task<byte[]> ProcessStreamFile(MultipartSection section,ContentDispositionHeaderValue contentDisposition, FileUploadOption fileUploadOption)
        {
            var filename = contentDisposition.FileName.Value;

            using var ms = new MemoryStream();
            await section.Body.CopyToAsync(ms);

            if(ms.Length == 0)
            {
                throw new Exception($"[{filename}] The file is empty.");
            }

            if(ms.Length > fileUploadOption.FileSizeLimit)
            {
                throw new Exception($"[{filename}] The file exceeds ${fileUploadOption.FileSizeLimit / 1048576:N1} MB.");
            }

            if(!IsValidFileExtension(filename, ms, fileUploadOption.SupportFiles))
            {
                throw new Exception($"[{filename}] The file type isn't permitted or the file's signature doesn't match the file's extension.");
            }

            return ms.ToArray();
        }





        /// <summary>
        /// 验证文件后缀是否支持
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="extension"></param>
        /// <returns></returns>
        private static bool IsValidFileExtension(string fileName, Stream data, List<string> supportFiles)
        {
            if(string.IsNullOrWhiteSpace(fileName))
            {
                return false;
            }
            var ext = Path.GetExtension(fileName).ToLowerInvariant();
            if(string.IsNullOrWhiteSpace(ext) || !supportFiles.Any(s=>s.ToLowerInvariant() == ext))
            {
                return false;
            }

            return true;
        }
    }
}
